package org.testis.utils.middleware;

import java.util.HashMap;
import java.util.LinkedList;
import org.orm.PersistentException;
import org.orm.PersistentTransaction;
import org.testis.orm.classes.*;
import org.testis.orm.manager.TestisDbPersistentManager;
import org.testis.orm.refinedclasses.DynamicMapDesignTreeNode;
import org.testis.orm.refinedclasses.DynamicMapObject;
import org.testis.utils.parametermodel.ParameterModel;
import org.testis.utils.parametermodel.ParameterTable;

/**
 * 
 * @author Cahit Emir Erel
 */
public class DynamicMap {

    private static DynamicMap m_reference = null;
    private HashMap<String, T_dmap_grouptype> m_groupTypes = new HashMap<String, T_dmap_grouptype>();
    private HashMap<String, T_dmap_type> m_types = new HashMap<String, T_dmap_type>();
    private HashMap<Integer, T_dmap_params> m_parameters = new HashMap<Integer, T_dmap_params>();
    private HashMap<String, T_bed_deviceabstraction> m_deviceAbstraction = new HashMap<String, T_bed_deviceabstraction>();
    private HashMap<String, T_dmap_abstract_objects> m_abstractObjects = new HashMap<String, T_dmap_abstract_objects>();

    private DynamicMap() {
	T_dmap_grouptype[] groupTypeList = getGroupTypeList();
	for (int i = 0; i < groupTypeList.length; i++) {
	    m_groupTypes.put(groupTypeList[i].getName(), groupTypeList[i]);
	    T_dmap_type[] typeList = groupTypeList[i].t_dmap_type.toArray();
	    for (int j = 0; j < typeList.length; j++) {
		m_types.put(typeList[j].getName(), typeList[j]);
		T_dmap_abstraction_pair[] abstractionPairList = typeList[j].t_dmap_abstraction_pair
			.toArray();
		for (int k = 0; k < abstractionPairList.length; k++) {
		    m_abstractObjects.put(abstractionPairList[k].getAbstract()
			    .getName(), abstractionPairList[k].getAbstract());
		}
	    }
	}
	try {
	    T_dmap_params[] paramList = T_dmap_paramsFactory
		    .listT_dmap_paramsByQuery(null, null);
	    for (int k = 0; k < paramList.length; k++) {
		m_parameters.put(paramList[k].getId(), paramList[k]);
	    }
	} catch (PersistentException ex) {
	}

	try {
	    T_bed_deviceabstraction[] abstractionList = T_bed_deviceabstractionFactory
		    .listT_bed_deviceabstractionByQuery(null, null);
	    for (int i = 0; i < abstractionList.length; i++) {
		m_deviceAbstraction.put(abstractionList[i].getName(),
			abstractionList[i]);
	    }
	} catch (PersistentException ex) {
	}
    }

    public int setRankOfAdd(DynamicMapDesignTreeNode parentNode,
	    T_dmap_designtree newNode, int childIndex)
	    throws PersistentException {
	if (parentNode == null) {
	    return -1;
	}
	int childCount = parentNode.getChildren().length;
	if (childIndex < 0) {
	    childIndex = 0;
	}
	if (childCount > 0) {
	    DynamicMapDesignTreeNode[] children = parentNode.getChildren();

	    if (childIndex == 0) {
		newNode.setRank(null);
		children[0].getReference().setRank(newNode.getId());
		children[0].getReference().save();
	    } else if (childIndex < childCount) {
		newNode.setRank(children[childIndex - 1].getId());
		children[childIndex].getReference().setRank(newNode.getId());
		children[childIndex].getReference().save();

	    } else {
		newNode.setRank(children[childCount - 1].getId());
	    }
	} else {
	    return -1;
	}
	return childIndex;
    }

    public DynamicMapDesignTreeNode operationPasteCopy(
	    DynamicMapDesignTreeNode copyObject,
	    DynamicMapDesignTreeNode parentNode, int childIndex)
	    throws PersistentException {
	DynamicMapDesignTreeNode newCopy = null;
	newCopy = copyObject.createRefinedDatabaseCopy(
		parentNode.getReference(), null);
	if (newCopy == null) {
	    return null;
	}
	int place = -1;
	place = setRankOfAdd(parentNode, newCopy.getReference(), childIndex);
	newCopy.getReference().save();
	if (place == -1) {
	    parentNode.addChild(newCopy);
	} else {
	    parentNode.addChild(place, newCopy);
	    newCopy.setPlace(place);
	}
	return newCopy;
    }

    public DynamicMapDesignTreeNode operationPasteClone(
	    DynamicMapDesignTreeNode cloneObject,
	    DynamicMapDesignTreeNode parentTreeNode, int childIndex)
	    throws PersistentException {

	T_dmap_designtree parentDesignTree = parentTreeNode.getReference();
	T_dmap_designtree newClone = new T_dmap_designtree();
	newClone.setParent(parentDesignTree);
	if (cloneObject.isClone()) {
	    newClone.setClone(cloneObject.getReference().getClone());
	} else {
	    newClone.setClone(cloneObject.getReference());
	}
	newClone.setFirmware(null);
	newClone.setObject(null);
	if (newClone.save()) {
	    int place = -1;
	    place = setRankOfAdd(parentTreeNode, newClone, childIndex);
	    DynamicMapDesignTreeNode newNode = DynamicMapDesignTreeNode
		    .getNode(newClone);
	    if (place == -1) {
		parentTreeNode.addChild(newNode);
	    } else {
		parentTreeNode.addChild(place, newNode);
		newNode.setPlace(place);
	    }
	    newClone.save();
	    return newNode;
	}
	return null;
    }

    public T_dmap_params getParamByTypeandName(String type, String name) {
	T_dmap_params[] paramList = m_types.get(type).t_dmap_params.toArray();
	for (int i = 0; i < paramList.length; i++) {
	    if (paramList[i].getName().equals(name)) {
		return paramList[i];
	    }
	}
	return null;
    }

    public T_dmap_params getParamById(int id) {
	return m_parameters.get(id);
    }

    public static final DynamicMap newInstance() {
	if (m_reference == null) {
	    m_reference = new DynamicMap();
	}
	return m_reference;
    }

    public T_dmap_abstract_objects getAbstractObjectByName(String name) {
	return m_abstractObjects.get(name);
    }

    public String[] getGroupTypes() {
	String[] results = null;
	T_dmap_grouptype[] groupTypeList = m_groupTypes.values().toArray(
		new T_dmap_grouptype[m_groupTypes.size()]);
	results = new String[groupTypeList.length];
	for (int i = 0; i < groupTypeList.length; i++) {
	    results[i] = groupTypeList[i].getName();
	}
	return results;
    }

    public T_dmap_grouptype getGroupTypes(String name) {
	return m_groupTypes.get(name);
    }

    public T_dmap_grouptype[] getGroupTypeList() {
	try {
	    return T_dmap_grouptypeFactory.listT_dmap_grouptypeByQuery(null,
		    null);
	} catch (PersistentException ex) {
	    System.err.println("Uanble to get Group Type List from database");
	}
	return new T_dmap_grouptype[0];
    }

    public String[] getTypes(String groupType) {
	String[] results = null;
	T_dmap_type[] typeList = getTypeList(groupType);
	results = new String[typeList.length];
	for (int i = 0; i < typeList.length; i++) {
	    results[i] = typeList[i].getName();
	}
	return results;
    }

    public T_dmap_type[] getTypeList(String groupType) {
	return m_groupTypes.get(groupType).t_dmap_type.toArray();
    }

    public T_dmap_type getTypeByName(String name) {
	return m_types.get(name);
    }

    public String[] getParameters(String type) {
	String[] results = null;
	T_dmap_params[] params = m_types.get(type).t_dmap_params.toArray();
	results = new String[params.length];
	for (int i = 0; i < params.length; i++) {
	    results[i] = params[i].getName();
	}
	return results;
    }

    public String[] getAbstractValues(String type) {
	String[] results = null;
	T_dmap_abstraction_pair[] pairs = m_types.get(type).t_dmap_abstraction_pair
		.toArray();
	results = new String[pairs.length];
	for (int i = 0; i < pairs.length; i++) {
	    results[i] = pairs[i].getAbstract().getName();
	}
	return results;
    }

    public DynamicMapDesignTreeNode getDynamicMapDesignTreeFomDB(
	    boolean showReport, String firmware, String dut)
	    throws PersistentException {
	return getDynamicMapDesignTreeDataFomDB(showReport, firmware, dut);
    }

    public DynamicMapDesignTreeNode getDynamicMapDesignTreeFomDB(
	    int designTreeId) throws PersistentException {
	T_dmap_designtree tree = null;
	if (tree == null) {
	    T_dmap_designtreeCriteria crit = new T_dmap_designtreeCriteria();
	    crit.id.eq(designTreeId);
	    tree = crit.uniqueT_dmap_designtree();
	    if (tree == null) {
		throw new NoSuchDeviceException();
	    }
	}
	return constructDynamicMap(tree);
    }

    public DynamicMapDesignTreeNode getDynamicMapDesignTreeFomDB(
	    boolean showReport, int deviceId) throws PersistentException {
	T_dmap_designtreeCriteria crit = new T_dmap_designtreeCriteria();
	crit.id.eq(getDutById(deviceId).getActiveFirmware().getDeviceMap()
		.getId());
	T_dmap_designtree tree = crit.uniqueT_dmap_designtree();

	if (tree != null) {
	    DynamicMapDesignTreeNode result = constructDynamicMap(tree);
	    if (showReport) {
		showRootTree(result, "");
	    }
	    return result;
	} else {
	    throw new NoSuchDeviceException();
	}
    }

    public T_bed_dut getDutByName(String name) {
	T_bed_dutCriteria dutList;
	try {
	    dutList = new T_bed_dutCriteria();
	    dutList.name.eq(name);
	    return dutList.uniqueT_bed_dut();
	} catch (PersistentException ex) {
	}
	return null;
    }

    public T_bed_dut getDutById(int id) {
	T_bed_dutCriteria dutList;
	try {
	    dutList = new T_bed_dutCriteria();
	    dutList.id.eq(id);
	    return dutList.uniqueT_bed_dut();
	} catch (PersistentException ex) {
	}
	return null;
    }

    public String[] getFirmwaresByDutName(String dut) {
	T_bed_firmware[] firmwareList = getFirmwareListByDutName(dut);
	// System.out.println(firmwareList.length);
	String[] results = new String[firmwareList.length];
	for (int i = 0; i < firmwareList.length; i++) {
	    results[i] = firmwareList[i].getName();
	}
	return results;
    }

    public T_bed_dut[] getDutList() {
	try {
	    return T_bed_dutFactory.listT_bed_dutByQuery(null, null);
	} catch (PersistentException ex) {
	}
	return null;
    }

    public String[] getDuts() {
	T_bed_dut[] duts = getDutList();
	String[] dutsList = null;
	if (duts != null) {
	    dutsList = new String[duts.length];
	    for (int i = 0; i < duts.length; i++) {
		dutsList[i] = duts[i].getName();
	    }
	}
	return dutsList;
    }

    private T_bed_firmware[] getFirmwareListByDutName(String name) {
	try {
	    // System.out.println(m_duts.get(dut).getDeviceDefinition());
	    T_bed_dut dut = getDutByName(name);
	    if (dut != null) {
		return dut.getDeviceDefinition().t_bed_firmware.toArray();
	    }
	    return new T_bed_firmware[0];
	} catch (NullPointerException ex) {
	    ex.printStackTrace();
	    return new T_bed_firmware[0];
	}
    }

    public T_bed_firmware getFirmwareByNameAndDutName(String firmwareName,
	    String dutName) {
	T_bed_firmware[] firmwareList = getFirmwareListByDutName(dutName);
	for (int i = 0; i < firmwareList.length; i++) {
	    if (firmwareList[i].getName().equals(firmwareName)) {
		return firmwareList[i];
	    }
	}
	return null;
    }

    private DynamicMapDesignTreeNode getDynamicMapDesignTreeDataFomDB(
	    boolean showReport, String firmware, String dut)
	    throws PersistentException {
	T_bed_firmware firm = getFirmwareByNameAndDutName(firmware, dut);
	if (firm == null) {
	    throw new NoSuchDeviceException();
	}
	T_dmap_designtreeCriteria crit = new T_dmap_designtreeCriteria();
	crit.id.eq(firm.getDeviceMap().getId());
	T_dmap_designtree rootDesignTree = crit.uniqueT_dmap_designtree();

	if (rootDesignTree == null) {
	    throw new NoSuchDynamicMapException();
	}
	DynamicMapDesignTreeNode result = constructDynamicMap(rootDesignTree);
	if (showReport) {
	    showRootTree(result, "");
	}
	return result;
    }

    public DynamicMapDesignTreeNode contructPartialDynamicMap(
	    T_dmap_designtree node) {
	try {
	    return constructDynamicMap(node);
	} catch (PersistentException ex) {
	    return null;
	}
    }

    private DynamicMapDesignTreeNode constructDynamicMap(
	    T_dmap_designtree reference) throws PersistentException {
	DynamicMapDesignTreeNode node = DynamicMapDesignTreeNode
		.getNode(reference);
	T_dmap_designtree[] children = reference.t_dmap_designtree.toArray();
	if (children != null && children.length > 0) {
	    T_dmap_designtree eldestSibling = null;
	    for (int i = 0; i < children.length; i++) {
		if (children[i].getRank() == null) {
		    eldestSibling = children[i];
		    break;
		}
	    }
	    if (eldestSibling == null) {
		throw new PersistentException(
			"CHILD ERROR! NO CHILD WITH RANK NULL. Check nodes with parentid: "
				+ reference.getId());
	    }
	    LinkedList<T_dmap_designtree> childrenLinkedList = new LinkedList<T_dmap_designtree>();
	    boolean flag;
	    do {
		flag = false;
		childrenLinkedList.add(eldestSibling);
		for (int i = 0; i < children.length; i++) {
		    if (children[i].getRank() != null
			    && eldestSibling.getId() == children[i].getRank()
				    .intValue()) {
			eldestSibling = children[i];
			flag = true;
			break;
		    }
		}
	    } while (flag);
	    if (childrenLinkedList.size() != children.length) {
		System.out.println("EXCEPTION BAD LINK! WRONG NO OF CHILDREN= "
			+ childrenLinkedList.size());
		throw new PersistentException();
	    }
	    for (int i = 0; i < childrenLinkedList.size(); i++) {
		node.addChild(constructDynamicMap(childrenLinkedList.get(i)));
	    }
	}
	return node;
    }

    public void showRootTree(DynamicMapDesignTreeNode tree, String start) {
	DynamicMapDesignTreeNode next = null;
	// System.out.println(start+tree.getObject().toString());
	DynamicMapDesignTreeNode[] children = tree.getChildren();
	start += "\t";
	for (int i = 0; i < children.length; i++) {
	    next = children[i];
	    // System.out.println(start);
	    showRootTree(next, start);
	}
    }

    public DynamicMapDesignTreeNode operationAddNewObject(
	    HashMap<String, Object> paraMap, DynamicMapDesignTreeNode parent,
	    int childIndex) {
	String name = (String) paraMap.get("name");
	ParameterTable parameterTable = (ParameterTable) paraMap
		.get("parameters");
	String type = (String) paraMap.get("type");
	T_dmap_designtree parentNode;
	// DynamicMapObject parentObject;
	ParameterModel[] params;
	DynamicMapDesignTreeNode parentTreeNode = null;
	if (parent instanceof DynamicMapDesignTreeNode) {
	    parentTreeNode = (DynamicMapDesignTreeNode) parent;
	    parentNode = parentTreeNode.getReference();
	} else {
	    parentNode = null;
	}

	params = parameterTable.getAllItems();

	try {
	    PersistentTransaction t = TestisDbPersistentManager.instance()
		    .getSession().beginTransaction();
	    try {
		String value;
		T_dmap_designtree newT_dmap_designtree;
		T_dmap_objects newObject;
		T_dmap_objectpair newObjectPair;
		T_dmap_abstraction_pair newT_dmap_abstraction_pair;
		T_dmap_abstract_objects newT_dmap_abstract_objects = null;

		newObject = new T_dmap_objects();
		newObject.setName(name);
		newObject.setType(m_types.get(type));
		newObject.save();

		for (int i = 0; i < params.length; i++) {
		    newObjectPair = new T_dmap_objectpair();
		    value = params[i].getValue().trim();
		    if (params[i].getParameter() != null
			    && params[i].getParameter().equals("AbstractId")) {
			if (getAbstractObjectByName(value) == null) {
			    newT_dmap_abstract_objects = new T_dmap_abstract_objects();
			    newT_dmap_abstract_objects.setName(value);
			    newT_dmap_abstract_objects
				    .setDeviceAbstraction(m_deviceAbstraction
					    .get("ASP"));
			    newT_dmap_abstract_objects.save();

			    newT_dmap_abstraction_pair = new T_dmap_abstraction_pair();
			    newT_dmap_abstraction_pair
				    .setAbstract(newT_dmap_abstract_objects);
			    newT_dmap_abstraction_pair.setType(m_types
				    .get(type));
			    newT_dmap_abstraction_pair.save();
			}
		    }

		    newObjectPair.setObject(newObject);
		    newObjectPair.setParam(getParamByTypeandName(type,
			    params[i].getParameter()));
		    newObjectPair.setValue(value);
		    newObjectPair.save();
		}
		newT_dmap_designtree = new T_dmap_designtree();
		newT_dmap_designtree.setClone(null);
		newT_dmap_designtree.setFirmware(null);
		newT_dmap_designtree.setObject(newObject);
		newT_dmap_designtree.setParent(parentNode);
		newT_dmap_designtree.save();
		int place = -1;
		place = setRankOfAdd(parentTreeNode, newT_dmap_designtree,
			childIndex);
		DynamicMapDesignTreeNode newNode = DynamicMapDesignTreeNode
			.getNode(newT_dmap_designtree);
		if (parentTreeNode != null) {
		    if (place == -1) {
			parentTreeNode.addChild(newNode);
		    } else {
			parentTreeNode.addChild(place, newNode);
			newNode.setPlace(place);
		    }
		}
		if (newT_dmap_abstract_objects != null) {
		    m_abstractObjects.put(newT_dmap_abstract_objects.getName(),
			    newT_dmap_abstract_objects);
		}
		t.commit();
		return newNode;
	    } catch (PersistentException ex) {
		ex.printStackTrace();
		t.rollback();
	    } finally {
		TestisDbPersistentManager.instance().disposePersistentManager();
	    }
	} catch (PersistentException ex) {
	    ex.printStackTrace();
	}
	return null;
    }

    public void deleteAbstractObject(String value) throws PersistentException {
	T_dmap_abstract_objects abstractObject = DynamicMap.newInstance()
		.getAbstractObjectByName(value);
	T_dmap_abstraction_pair[] pairs = abstractObject.t_dmap_abstraction_pair
		.toArray();
	if (pairs != null && pairs.length > 0) {
	    for (int i = 0; i < pairs.length; i++) {
		if (!pairs[i].deleteAndDissociate()) {
		    throw new PersistentException(
			    "Unable to delete Abstract Object Pair");
		}
	    }
	}
	if (!abstractObject.deleteAndDissociate()) {
	    throw new PersistentException("Unable to delete Abstract Object");
	} else {
	    m_abstractObjects.remove(value);
	}
    }

    public boolean operationSaveNewObject(HashMap<String, Object> paraMap,
	    DynamicMapDesignTreeNode node) {
	String name = (String) paraMap.get("name");
	ParameterTable parameterTable = (ParameterTable) paraMap
		.get("parameters");
	String type = (String) paraMap.get("type");
	ParameterModel[] params;
	DynamicMapDesignTreeNode treeNode = (DynamicMapDesignTreeNode) node;
	// T_dmap_designtree reference = treeNode.getDesignTreeReference();
	DynamicMapObject object = treeNode.getObject();

	params = parameterTable.getAllItems();

	try {
	    PersistentTransaction t = TestisDbPersistentManager.instance()
		    .getSession().beginTransaction();
	    try {
		if (object.deleteParameters()) {
		    System.out.println("Parameters have been deleted");
		} else {
		    throw new PersistentException(
			    "FAILED to delete parameters!");
		}
		object.getReference().setName(name);
		if (!object.getReference().save()) {
		    throw new PersistentException(
			    "Could not change object's name");
		} else {
		    System.out.println("Object has been saved");
		}
		T_dmap_abstract_objects newT_dmap_abstract_objects = null;
		for (int i = 0; i < params.length; i++) {
		    if (params[i].getParameter().equals("AbstractId")) {
			if (getAbstractObjectByName(params[i].getValue().trim()) == null) {
			    // ASP ABSTRACTION IS DEFAULT
			    newT_dmap_abstract_objects = new T_dmap_abstract_objects();
			    newT_dmap_abstract_objects.setName(params[i]
				    .getValue().trim());
			    newT_dmap_abstract_objects
				    .setDeviceAbstraction(m_deviceAbstraction
					    .get("ASP"));
			    newT_dmap_abstract_objects.save();
			    T_dmap_abstraction_pair newT_dmap_abstraction_pair = new T_dmap_abstraction_pair();
			    newT_dmap_abstraction_pair
				    .setAbstract(newT_dmap_abstract_objects);
			    newT_dmap_abstraction_pair.setType(object
				    .getReference().getType());
			    newT_dmap_abstraction_pair.save();
			}
		    }
		    T_dmap_objectpair pair = new T_dmap_objectpair();
		    pair.setObject(object.getReference());
		    pair.setValue(params[i].getValue().trim());
		    pair.setParam(getParamByTypeandName(type,
			    params[i].getParameter()));
		    if (pair.save()) {
			System.out.println("Pair Saved succesfully!");
		    } else {
			throw new PersistentException("Pair Save FAILED!");
		    }
		}
		t.commit();
		treeNode.setObject(new DynamicMapObject(object.getReference()));
		T_dmap_designtree[] clones = treeNode.getClones();
		for (int i = 0; i < clones.length; i++) {
		    DynamicMapDesignTreeNode.getNode(clones[i]).setObject(
			    new DynamicMapObject(object.getReference()));
		}
		if (newT_dmap_abstract_objects != null) {
		    m_abstractObjects.put(newT_dmap_abstract_objects.getName(),
			    newT_dmap_abstract_objects);
		}
		return true;
	    } catch (PersistentException ex) {
		t.rollback();
		ex.printStackTrace();
	    } finally {
		TestisDbPersistentManager.instance().disposePersistentManager();
	    }
	} catch (PersistentException ex) {
	    ex.printStackTrace();
	}
	return false;
    }

    public DynamicMapDesignTreeNode getFlyWeightDynamicMapTree(LinkedList list) {
	try {
	    /*
	     * System.out.println(
	     * "GET TREE: XXXXXXXXXXXXXXXX: getFlyWeightDynamicMapTree");
	     */
	    DynamicMapDesignTreeNode root = null;
	    DynamicMapDesignTreeNode result = null;
	    DynamicMapDesignTreeNode parent = null;
	    DynamicMapDesignTreeNode tempResult = null;
	    T_dmap_designtree temp = null;
	    LinkedList<T_dmap_designtree> depthSortedNodeList = new LinkedList<T_dmap_designtree>();
	    LinkedList<Integer> depthSortedNumberList = new LinkedList<Integer>();
	    HashMap<Integer, DynamicMapDesignTreeNode> hashMap = new HashMap<Integer, DynamicMapDesignTreeNode>();
	    int depth;
	    int addPoint;
	    // System.out.println("LIST SIZE:" + list.size());
	    for (int i = 0; i < list.size(); i++) {
		depth = 0;
		addPoint = 0;
		temp = (T_dmap_designtree) list.get(i);
		while (temp.getParent() != null) {
		    depth++;
		    temp = temp.getParent();
		}
		for (int j = 0; j < depthSortedNumberList.size(); j++) {
		    if (depth <= depthSortedNumberList.get(j)) {
			addPoint = j;
			break;
		    }
		}
		if (depthSortedNumberList.size() == addPoint) {
		    depthSortedNumberList.add(depth);
		    depthSortedNodeList.add((T_dmap_designtree) list.get(i));
		} else {
		    depthSortedNumberList.add(addPoint, depth);
		    depthSortedNodeList.add(addPoint,
			    (T_dmap_designtree) list.get(i));
		}
	    }
	    // System.out.println("SORTED NODE LIST SIZE:" +
	    // depthSortedNodeList.size());
	    for (int i = 0; i < depthSortedNodeList.size(); i++) {
		temp = depthSortedNodeList.get(i);
		parent = hashMap.get(temp.getParent().getId());
		if (parent == null) {
		    parent = DynamicMapDesignTreeNode.getNode(temp.getParent());
		    hashMap.put(temp.getParent().getId(), parent);
		}
		constructFlyweightTree(parent, temp, hashMap);
		result = parent;
		/*
		 * if (result.getParent() != null) { continue; }
		 */
		temp = temp.getParent();
		while (temp.getParent() != null) {
		    temp = temp.getParent();
		    tempResult = hashMap.get(temp.getId());
		    if (tempResult == null) {
			tempResult = DynamicMapDesignTreeNode.getNode(temp);
			hashMap.put(temp.getId(), tempResult);
			if (result.getParent() == null) {
			    tempResult.addChild(result);
			}
		    } else {
			tempResult.addChild(result);
			break;
		    }
		    result = tempResult;
		}
		if (root == null) {
		    root = result;
		}
	    }
	    return root;
	} catch (PersistentException ex) {
	    return null;
	}
    }

    private void constructFlyweightTree(DynamicMapDesignTreeNode parent,
	    T_dmap_designtree traverseNode,
	    HashMap<Integer, DynamicMapDesignTreeNode> hashMap)
	    throws PersistentException {
	DynamicMapDesignTreeNode temp;
	T_dmap_designtree[] children;
	HashMap<Integer, T_dmap_designtree> hmap;
	LinkedList<DynamicMapDesignTreeNode> childrenLinkedList = new LinkedList<DynamicMapDesignTreeNode>();
	children = parent.getReference().t_dmap_designtree.toArray();
	if (children != null && children.length > 0) {
	    hmap = new HashMap(children.length);
	    T_dmap_designtree eldestSibling = null;
	    int id;
	    Integer nextRankId;
	    for (int i = 0; i < children.length; i++) {
		id = -1;
		nextRankId = children[i].getRank();
		if (nextRankId != null) {
		    id = nextRankId.intValue();
		}
		hmap.put(id, children[i]);
	    }
	    eldestSibling = hmap.remove(-1);
	    if (eldestSibling == null) {
		throw new PersistentException(
			"RANKING ERROR: FIRST CHILD SHOULD HAVE NULL RANK ! Check nodes with Parent Id: "
				+ parent.getId());
	    }
	    do {
		temp = hashMap.get(eldestSibling.getId());
		boolean nodeExists = true;
		if (temp == null) {
		    nodeExists = false;
		    temp = DynamicMapDesignTreeNode.getNode(eldestSibling);
		    hashMap.put(eldestSibling.getId(), temp);
		}
		if (traverseNode != null
			&& eldestSibling.getId() == traverseNode.getId()) {
		    constructFlyweightTree(temp, null, hashMap);
		}
		if (!nodeExists) {
		    parent.addChild(temp);
		}
		childrenLinkedList.add(temp);
		eldestSibling = hmap.remove(eldestSibling.getId());
	    } while (eldestSibling != null);

	    // THROUBLESHOOTING MESSAGE
	    if (children.length != childrenLinkedList.size()) {
		Integer treeId;
		Integer parentId;
		LinkedList<Integer> treeIds = new LinkedList<Integer>();
		LinkedList<Integer> parentIds = new LinkedList<Integer>();
		boolean add;
		for (int i = 0; i < childrenLinkedList.size(); i++) {
		    add = true;
		    treeId = childrenLinkedList.get(i).getId();
		    parentId = childrenLinkedList.get(i).getParent().getId();
		    for (int j = 0; j < parentIds.size(); j++) {
			if (parentIds.get(j) == parentId.intValue()) {
			    add = false;
			    break;
			}
		    }
		    if (add) {
			parentIds.add(parentId);
			treeIds.add(treeId);
		    }
		}
		StringBuffer buffer = new StringBuffer();
		System.out
			.println("WRONG NO OF CHILDREN ERROR: LINKED LIST RANK ERROR DETECTED!");
		buffer.append("WRONG NO OF CHILDREN ERROR: LINKED LIST RANK ERROR DETECTED!");
		buffer.append("\nCheck nodes with Parent Id");
		for (int i = 0; i < parentIds.size(); i++) {
		    buffer.append(" : " + parentIds.get(i));
		}
		if (parentIds.size() > 1) {
		    buffer.append("\nAlso Check nodes with Id");
		    for (int i = 0; i < treeIds.size(); i++) {
			buffer.append(" : " + treeIds.get(i));
		    }
		}
		throw new PersistentException(buffer.toString());
	    }
	}
    }

    public boolean convertCloneOfGhostToOriginal(T_dmap_designtree clone,
	    T_dmap_designtree ghost) {
	try {
	    PersistentTransaction t = TestisDbPersistentManager.instance()
		    .getSession().beginTransaction();
	    try {
		T_dmap_designtree[] children = clone.t_dmap_designtree
			.toArray();
		for (int i = 0; i < children.length; i++) {
		    children[i].setParent(ghost);
		    children[i].save();
		}
		children = clone.getParent().t_dmap_designtree.toArray();
		for (int i = 0; i < children.length; i++) {
		    if (children[i].getRank() != null
			    && children[i].getRank().intValue() == clone
				    .getId()) {
			children[i].setRank(ghost.getId());
			children[i].save();
			break;
		    }
		}
		ghost.setFirmware(clone.getFirmware());
		// ghost.setObject(clone.getObject());
		ghost.setParent(clone.getParent());
		ghost.setRank(clone.getRank());
		ghost.setClone(null);
		DynamicMapDesignTreeNode.getNode(clone.getParent())
			.deleteChild(DynamicMapDesignTreeNode.getNode(clone));
		ghost.save();
		clone.deleteAndDissociate();
		t.commit();
		return true;
	    } catch (PersistentException ex) {
		t.rollback();
	    }
	} catch (PersistentException ex) {
	}
	return false;
    }

    public boolean handleMoveObjectRanks(
	    DynamicMapDesignTreeNode currentPrevTreeNode,
	    DynamicMapDesignTreeNode currentNextTreeNode,
	    DynamicMapDesignTreeNode newPrevTreeNode,
	    DynamicMapDesignTreeNode newNextTreeNode,
	    DynamicMapDesignTreeNode currentTreeNode) {
	try {
	    PersistentTransaction t = TestisDbPersistentManager.instance()
		    .getSession().beginTransaction();
	    try {
		if (currentNextTreeNode != null) {
		    if (currentPrevTreeNode != null) {
			currentNextTreeNode.getReference().setRank(
				currentPrevTreeNode.getReference().getId());
		    } else {
			System.out
				.println("SETTING OLD NEXT NODE'S RANK TO NULL");
			currentNextTreeNode.getReference().setRank(null);
			System.out.println("new rank: "
				+ currentNextTreeNode.getReference().getRank());
		    }
		    if (!currentNextTreeNode.getReference().save()) {
			throw new PersistentException();
		    }
		}
		if (newNextTreeNode != null) {
		    newNextTreeNode.getReference().setRank(
			    currentTreeNode.getReference().getId());
		    if (!newNextTreeNode.getReference().save()) {
			throw new PersistentException();
		    }
		}
		if (newPrevTreeNode != null) {
		    currentTreeNode.getReference().setRank(
			    newPrevTreeNode.getReference().getId());
		    if (!currentTreeNode.getReference().save()) {
			throw new PersistentException();
		    }
		} else {
		    currentTreeNode.getReference().setRank(null);
		    if (!currentTreeNode.getReference().save()) {
			throw new PersistentException();
		    }
		}
		t.commit();
		return true;
	    } catch (PersistentException e) {
		e.printStackTrace();
		t.rollback();
		return false;
	    } finally {
		TestisDbPersistentManager.instance().disposePersistentManager();
	    }
	} catch (PersistentException e) {
	    return false;
	}
    }

    public void fixChildren(DynamicMapDesignTreeNode parent) {
	if (parent.getReference() == null) {
	    return;
	}
	if (parent.getReference().t_dmap_designtree == null) {
	    return;
	}
	T_dmap_designtree[] children = parent.getReference().t_dmap_designtree
		.toArray();
	HashMap<Integer, T_dmap_designtree> sortedChildList = new HashMap<Integer, T_dmap_designtree>();
	for (int i = 0; i < children.length; i++) {
	    if (children[i].getRank() == null) {
		sortedChildList.put(0, children[i]);
	    } else {
		sortedChildList.put(children[i].getRank(), children[i]);
	    }
	}
	T_dmap_designtree temp;
	int nextChild = 0;
	while (sortedChildList.containsKey(nextChild)) {
	    temp = sortedChildList.get(nextChild);
	    nextChild = temp.getId();
	    parent.addChild(DynamicMapDesignTreeNode.getNode(temp));
	}
    }
}
